// ==================== 多生产多消费模型 ===============================
#pragma once

#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

template <class T>
class RingQueue
{
public:
public:
    RingQueue(int Default_cap = 5)
        : ringQueue(Default_cap), _cap(Default_cap), c_step(0), p_step(0)
    {
        sem_init(&c_sem, 0, 0);
        sem_init(&p_sem, 0, _cap);

        pthread_mutex_init(&c_mutex, nullptr);
        pthread_mutex_init(&p_mutex, nullptr);
    }

    ~RingQueue()
    {
        sem_destroy(&c_sem);
        sem_destroy(&p_sem);

        pthread_mutex_destroy(&c_mutex);
        pthread_mutex_destroy(&p_mutex);
    }

    // 生产数据
    void push(const T &in)
    {
        // 1. 先申请信号量资源 - P操作
        sem_wait(&p_sem);
        // 加锁
        pthread_mutex_lock(&p_mutex);
        // 2. 生产数据
        ringQueue[p_step] = in;
        // 维持环形特征
        p_step++;
        p_step %= _cap;
        // 解锁
        pthread_mutex_unlock(&p_mutex);

        // 3. 数据多了一个 - V操作
        sem_post(&c_sem);
    }

    // 消费数据
    void Pop(T *out)
    {
        // 1. 先申请信号量资源 - P操作
        sem_wait(&c_sem);
        // 加锁
        pthread_mutex_lock(&c_mutex);
        // 2. 消费数据
        *out = ringQueue[c_step];
        // 维持环形特征
        c_step++;
        c_step %= _cap;
        // 解锁
        pthread_mutex_unlock(&c_mutex);
        // 3. 空间多了一个 - V操作
        sem_post(&p_sem);
    }

private:
    std::vector<T> ringQueue; // 数组模拟环形队列
    int _cap;                 // 环形队列的容量

    int c_step; // 消费者下标
    int p_step; // 生产者下标

    sem_t c_sem; // 消费者关注的数据资源
    sem_t p_sem; // 生产者关注的空间资源

    pthread_mutex_t c_mutex; // 消费者的锁
    pthread_mutex_t p_mutex; // 生产者的锁
};

// ==================== 单生产单消费模型 ===============================
// #pragma once

// #include <iostream>
// #include <vector>
// #include <semaphore.h>

// template <class T>
// class RingQueue
// {
// public:
// public:
//     RingQueue(int Default_cap = 5)
//         : ringQueue(Default_cap), _cap(Default_cap), c_step(0), p_step(0)
//     {
//         sem_init(&c_sem, 0, 0);
//         sem_init(&p_sem, 0, _cap);
//     }

//     ~RingQueue()
//     {
//         sem_destroy(&c_sem);
//         sem_destroy(&p_sem);
//     }

//     // 生产数据
//     void push(const T &in)
//     {
//         // 1. 先申请信号量资源 - P操作
//         sem_wait(&p_sem);
//         // 2. 生产数据
//         ringQueue[p_step] = in;
//         // 3. 数据多了一个 - V操作
//         sem_post(&c_sem);

//         // 维持环形特征
//         p_step++;
//         p_step %= _cap;
//     }

//     // 消费数据
//     void Pop(T *out)
//     {
//         // 1. 先申请信号量资源 - P操作
//         sem_wait(&c_sem);
//         // 2. 消费数据
//         *out = ringQueue[c_step];
//         // 3. 空间多了一个 - V操作
//         sem_post(&p_sem);

//         // 维持环形特征
//         c_step++;
//         c_step %= _cap;
//     }

// private:
//     std::vector<T> ringQueue; // 数组模拟环形队列
//     int _cap;                 // 环形队列的容量

//     int c_step; // 消费者下标
//     int p_step; // 生产者下标

//     sem_t c_sem; // 消费者关注的数据资源
//     sem_t p_sem; // 生产者关注的空间资源
// };
